package com.sdk.bigdata.client;

import com.sdk.bigdata.exceptions.DataConfigLoadException;
import com.sdk.bigdata.exceptions.PropertiesLoadException;
import com.sdk.bigdata.model.*;
import com.sdk.bigdata.utils.LoggerUtil;
import com.sdk.bigdata.utils.OkHttpUtils;
import com.sdk.bigdata.utils.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static com.sdk.bigdata.constant.Constants.*;


public class DataClient{
    private DataConfig conf;
    private volatile DataProducer producer;
    private volatile DataConsumer consumer;
    private Logger logger;

    DataClient() throws PropertiesLoadException {
        this.conf = PropertiesUtil.getConfig();
        try {
            int status = OkHttpUtils.ping(this.conf.getUrl() + "/Ping");
            if (status != 200) {
                throw new PropertiesLoadException("该上报地址连接失败,url=" + this.conf.getUrl());
            }
        } catch (IOException e) {
            throw new PropertiesLoadException("该上报地址连接失败,url=" + this.conf.getUrl());
        }
        initDataClient();
    }

    DataClient(DataConfig dataConfig) throws DataConfigLoadException {
        PropertiesUtil.checkDataConfig(dataConfig);
        this.conf = dataConfig;
        try {
            int status = OkHttpUtils.ping(this.conf.getUrl() + "/Ping");
            if (status != 200) {
                throw new DataConfigLoadException("该上报地址连接失败,url=" + this.conf.getUrl());
            }
        } catch (IOException e) {
            throw new DataConfigLoadException("该上报地址连接失败,url=" + this.conf.getUrl());
        }
        this.conf = dataConfig;
        initDataClient();
    }

    private void initDataClient() {
        this.producer = new DataProducer(conf.getMaxSize(), conf.getMaxQueue());
        this.consumer = new DataConsumer(conf);
        logger = LoggerFactory.getLogger(DataClient.class);
        // 当程序接收到系统结束时，关闭consumer且清空缓冲数据
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            if (null != consumer) {
                consumer.close();
            }
        }));
    }

    private void send(BaseModel baseModel) {
        if (this.consumer == null) {
            synchronized (DataClient.class) {
                if (this.consumer == null) {
                    this.consumer = new DataConsumer(conf);
                }
            }
        }
        if (consumer.getQueueSize() >= conf.getMaxQueue()) {
            LoggerUtil.log(logger, ERROR, "拒绝了请求，目前容器数量过大，不能继续添加");
        } else {
            this.producer.send(baseModel);
        }
    }

    // 用户行为事件
    public void Action(String event, String uid, String uidType, Map<String, Object> properties) {
        Action action = new Action(TYPE_ACTION, event, uid, uidType, properties);
        send(action);
    }

    // 设备行为事件
    public void Device(String event, String deviceNo, String deviceType, String deviceName, Map<String, Object> properties) {
        Device device = new Device(TYPE_DEVICE, event, deviceNo, deviceType, deviceName, properties);
        send(device);
    }

    // 实体信息
    public void Entity(String entity, String entityId, Map<String, Object> properties) {
        Entity entitys = new Entity(TYPE_ENTITY, entity, entityId, properties);
        send(entitys);
    }

    // 用户信息设置
    public void ProfileSet(String uid, String uidType, Map<String, Object> properties) {
        User user = new User(TYPE_PROFILE_SET, uid, uidType, properties);
        send(user);
    }

    // 创建物品
    public void ItemSet(String itemId, String itemType, String name, Double price, Map<String, Object> properties) {
        Item item = new Item(TYPE_ITEM_SET, itemId, itemType, name, price, properties);
        send(item);
    }

    //  删除物品
    public void ItemDelete(String itemId, String itemType) {
        Item item = new Item(TYPE_ITEM_DELETE, itemId, itemType, "name", 0.0, new HashMap<>());
        send(item);
    }

    //  创建礼包
    public void BundleSet(String bundleId, String name, Double price, int[][] items, Map<String, Object> properties) {
        Bundle bundle = new Bundle(TYPE_BUNDLE_SET, bundleId, name, price, items, properties);
        send(bundle);
    }

    //  删除礼包
    public void BundleDelete(String bundleId) {
        int[][] items = {};
        Bundle bundle = new Bundle(TYPE_BUNDLE_DELETE, bundleId, "name", 0.0, items, new HashMap<>());
        send(bundle);
    }

    public void close() {
        this.consumer.close();
        this.consumer = null;
    }

}
